package com.example.user.service.contest.impl;

import cn.hutool.core.collection.CollectionUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.example.common.core.constants.Constants;
import com.example.common.core.domain.TableDataInfo;
import com.example.common.core.enums.ContestListType;
import com.example.common.core.enums.ResultCode;
import com.example.common.core.utils.ThreadLocalUtil;
import com.example.common.security.exception.ServiceException;
import com.example.common.security.service.TokenService;
import com.example.user.domain.contest.Contest;
import com.example.user.domain.contest.UserContest;
import com.example.user.domain.contest.dto.ContestDTO;
import com.example.user.domain.contest.dto.ContestQueryDTO;
import com.example.user.domain.contest.vo.ContestVO;
import com.example.user.manager.ContestCacheManager;
import com.example.user.mapper.contest.ContestMapper;
import com.example.user.mapper.contest.UserContestMapper;
import com.example.user.service.contest.UserContestService;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import java.time.LocalDateTime;
import java.util.List;

@Service
public class UserContestServiceImpl implements UserContestService {
    @Autowired
    private ContestMapper contestMapper;

    @Autowired
    private UserContestMapper userContestMapper;

    @Autowired
    private TokenService tokenService;

    @Value("${jwt.secret}")
    private String secret;

    @Autowired
    private ContestCacheManager contestCacheManager;

    @Override
    public int enter(String token, ContestDTO contestDTO) {
        Contest contest = contestMapper.selectById(contestDTO.getContestId());
        if (contest == null) {
            throw new ServiceException(ResultCode.EXAM_NOT_EXISTS);
        }
        if (contest.getStartTime().isBefore(LocalDateTime.now())) {
            throw new ServiceException(ResultCode.EXAM_STARTED);
        }
        Long userId = ThreadLocalUtil.get(Constants.USER_ID, Long.class);
        UserContest userContest = userContestMapper.selectOne(new LambdaQueryWrapper<UserContest>()
                .eq(UserContest::getContestId, contestDTO.getContestId())
                .eq(UserContest::getUserId,userId));
        if (userContest != null) {
            throw new ServiceException(ResultCode.USER_EXAM_HAS_ENTER);
        }
        userContest = new UserContest();
        userContest.setContestId(contestDTO.getContestId());
        userContest.setUserId(userId);
        contestCacheManager.addUserContestCache(userId,contestDTO.getContestId());
        return userContestMapper.insert(userContest);


    }

    @Override
    public TableDataInfo list(ContestQueryDTO contestQueryDTO) {
        Long userId = ThreadLocalUtil.get(Constants.USER_ID, Long.class);
        Long total = contestCacheManager.getListSize(ContestListType.USER_CONTEST_LIST.getValue(),userId);
        List<ContestVO> result;
        if (total == null || total == 0) {
            PageHelper.startPage(contestQueryDTO.getPageNum(), contestQueryDTO.getPageSize());
            result = userContestMapper.selectUserContestList(userId);
            contestCacheManager.refreshCache(contestQueryDTO.getType(),null);
            total = new PageInfo<>(result).getTotal();

        }else {
            result =contestCacheManager.getContestVOList(contestQueryDTO,null);
            total = contestCacheManager.getListSize(contestQueryDTO.getType(),null); //有问题 不是真正的总数
        }
        if (CollectionUtil.isEmpty(result)) {
            return TableDataInfo.empty();
        }
        assembleContestVOList(result);
        return TableDataInfo.success(result, total);
    }

    private void assembleContestVOList(List<ContestVO> contestVOList) {
        Long userId = ThreadLocalUtil.get(Constants.USER_ID, Long.class);
        List<Long> userContestIdList = contestCacheManager.getAllUserContestList(userId);
        if (CollectionUtil.isEmpty(userContestIdList)) {
            return;
        }
        for (ContestVO contestVO : contestVOList) {
            if (userContestIdList.contains(contestVO.getId())) {
                contestVO.setEnter(true);
            }
        }
    }
}
